/**
 * @file SimpleCDNET.cpp
 * @brief SimpleCDNET Arduino库实现
 * @details 为Arduino平台提供CDNET协议栈的完整实现
 *          支持Layer 0和Layer 1协议，包括：
 *          - 数据包构造和解析
 *          - 网络层路由
 *          - 套接字管理
 *          - 多播支持
 *          - 多网络支持
 * 
 * @author 修改团队：mastwet@Undefine Innovation
 * @date 2024
 * @copyright MIT License
 * 
 * @section 功能特性
 * - 支持CDNET Layer 0协议（8位端口）
 * - 支持CDNET Layer 1协议（16位端口）
 * - 内置数据包缓冲池管理
 * - 支持网络路由和多播
 * - 与CDBUS底层协议栈无缝集成
 * 
 * @section 使用示例
 * @code
 * #include <SimpleCDNET.h>
 * 
 * SimpleCDNET cdnet;
 * 
 * void setup() {
 *     Serial.begin(115200);
 *     cdnet.begin(&Serial, 0x01);  // 网络ID=0, MAC地址=0x01
 * }
 * 
 * void loop() {
 *     uint8_t src, port, buffer[64];
 *     if (cdnet.readL0(&src, &port, buffer, sizeof(buffer)) > 0) {
 *         // 处理Layer 0数据
 *     }
 * }
 * @endcode
 * 
 * @warning 需要先初始化CDBUS底层协议栈
 * @warning 最大数据包长度受限于底层协议栈
 */

#include "SimpleCDNET.h"

/**
 * @brief 构造函数
 * @details 初始化CDNET协议栈，包括：
 *          - 初始化数据包缓冲池
 *          - 初始化帧缓冲池
 *          - 设置默认网络参数
 * 
 * @note 默认网络ID为0，MAC地址为0
 * @note 默认禁用多播和多网络功能
 */
SimpleCDNET::SimpleCDNET() : _net_id(0), _mac_address(0), _multicast_enabled(false), _multi_net_enabled(false) {
    /* 初始化数据包缓冲池 */
    list_init(&_free_pkt);
    list_init(&_free_frm);
    
    /* 填充空闲缓冲池 */
    for (int i = 0; i < 8; i++) {
        list_put(&_free_pkt, &_pkt_pool[i].node);
        list_put(&_free_frm, &_frame_pool[i].node);
    }
}

/**
 * @brief 初始化CDNET协议栈（单网络版本）
 * @param serial 硬件串口指针
 * @param address MAC地址
 * @details 使用默认网络ID(0)初始化协议栈
 * 
 * @note 适用于单网络环境
 * @note 自动配置CDBUS底层协议栈
 */
void SimpleCDNET::begin(HardwareSerial *serial, uint8_t address) {
    _net_id = 0;
    _mac_address = address;
    _cdbus.begin(serial, address);
    initializeCDNET();
    initializeCore();
}

/**
 * @brief 初始化CDNET协议栈（多网络版本）
 * @param serial 硬件串口指针
 * @param net_id 网络ID
 * @param mac_address MAC地址
 * @details 支持多网络环境的协议栈初始化
 * 
 * @note 适用于多网络环境
 * @note 需要确保网络ID的唯一性
 */
void SimpleCDNET::begin(HardwareSerial *serial, uint8_t net_id, uint8_t mac_address) {
    _net_id = net_id;
    _mac_address = mac_address;
    _cdbus.begin(serial, mac_address);
    initializeCDNET();
    initializeCore();
}

/**
 * @brief 关闭CDNET协议栈
 * @details 关闭底层CDBUS协议栈
 *          释放相关资源
 */
void SimpleCDNET::end() {
    _cdbus.end();
}

/**
 * @brief 发送Layer 0数据包
 * @param dst 目标地址
 * @param port 端口号（8位）
 * @param data 数据缓冲区
 * @param len 数据长度
 * @details 构造并发送Layer 0协议数据包
 * 
 * @note 使用8位端口号（0-255）
 * @note 最大数据长度受限于CDNET_MAX_PACKET_SIZE
 */
void SimpleCDNET::sendL0(uint8_t dst, uint8_t port, uint8_t *data, uint8_t len) {
    uint8_t temp_buffer[CDNET_MAX_PACKET_SIZE];
    int frame_len = cdnet_create_l0_frame(port, data, len, temp_buffer);
    
    if (frame_len > 0) {
        _cdbus.send(dst, temp_buffer, frame_len);
    }
}

/**
 * @brief 发送Layer 1数据包
 * @param dst 目标地址
 * @param port 端口号（16位）
 * @param data 数据缓冲区
 * @param len 数据长度
 * @details 构造并发送Layer 1协议数据包
 * 
 * @note 使用16位端口号（0-65535）
 * @note 支持更大的地址空间
 */
void SimpleCDNET::sendL1(uint8_t dst, uint16_t port, uint8_t *data, uint8_t len) {
    uint8_t temp_buffer[CDNET_MAX_PACKET_SIZE];
    int frame_len = cdnet_create_l1_frame(port, data, len, temp_buffer);
    
    if (frame_len > 0) {
        _cdbus.send(dst, temp_buffer, frame_len);
    }
}

/**
 * @brief 读取Layer 0数据包
 * @param src 源地址缓冲区（可为NULL）
 * @param port 端口号缓冲区（可为NULL）
 * @param buffer 数据缓冲区
 * @param max_len 最大读取长度
 * @return 实际读取的数据长度，0表示无数据或格式错误
 * @details 解析并读取Layer 0协议数据包
 * 
 * @note 自动验证数据包格式
 * @note 自动处理地址和端口提取
 */
uint8_t SimpleCDNET::readL0(uint8_t *src, uint8_t *port, uint8_t *buffer, uint8_t max_len) {
    if (!_cdbus.available()) return 0;
    
    cdbus_frame_t frame;
    uint8_t src_addr;
    uint8_t temp_buffer[CDBUS_MAX_DATA_SIZE];
    
    /* 读取底层数据帧 */
    uint8_t len = _cdbus.read(&src_addr, temp_buffer, sizeof(temp_buffer));
    if (len < 2 || temp_buffer[0] != CDNET_TYPE_L0) return 0;
    
    /* 解析Layer 0数据包格式 */
    uint8_t actual_port = temp_buffer[1];
    uint8_t data_len = len - 2;
    
    /* 返回源地址和端口 */
    if (src) *src = src_addr;
    if (port) *port = actual_port;
    
    /* 复制数据到用户缓冲区 */
    uint8_t copy_len = min(data_len, max_len);
    if (buffer && copy_len > 0) {
        memcpy(buffer, &temp_buffer[2], copy_len);
    }
    
    return copy_len;
}

/**
 * @brief 读取Layer 1数据包
 * @param src 源地址缓冲区（可为NULL）
 * @param port 端口号缓冲区（可为NULL）
 * @param buffer 数据缓冲区
 * @param max_len 最大读取长度
 * @return 实际读取的数据长度，0表示无数据或格式错误
 * @details 解析并读取Layer 1协议数据包
 * 
 * @note 自动验证数据包格式
 * @note 支持16位端口号解析
 */
uint8_t SimpleCDNET::readL1(uint8_t *src, uint16_t *port, uint8_t *buffer, uint8_t max_len) {
    if (!_cdbus.available()) return 0;
    
    cdbus_frame_t frame;
    uint8_t src_addr;
    uint8_t temp_buffer[CDBUS_MAX_DATA_SIZE];
    
    /* 读取底层数据帧 */
    uint8_t len = _cdbus.read(&src_addr, temp_buffer, sizeof(temp_buffer));
    if (len < 3 || temp_buffer[0] != CDNET_TYPE_L1) return 0;
    
    /* 解析Layer 1数据包格式 */
    uint16_t actual_port = (temp_buffer[1] << 8) | temp_buffer[2];
    uint8_t data_len = len - 3;
    
    /* 返回源地址和端口 */
    if (src) *src = src_addr;
    if (port) *port = actual_port;
    
    /* 复制数据到用户缓冲区 */
    uint8_t copy_len = min(data_len, max_len);
    if (buffer && copy_len > 0) {
        memcpy(buffer, &temp_buffer[3], copy_len);
    }
    
    return copy_len;
}

/**
 * @brief 检查是否有数据可读取
 * @return true有数据，false无数据
 * @details 委托给底层CDBUS协议栈
 */
bool SimpleCDNET::available() {
    return _cdbus.available();
}

/**
 * @brief 更新协议栈状态
 * @details 更新底层CDBUS协议栈状态
 *          处理接收和发送队列
 */
void SimpleCDNET::update() {
    _cdbus.update();
}

/**
 * @brief 设置地址过滤器
 * @param filter 过滤器值
 * @details 设置底层CDBUS的地址过滤器
 * 
 * @note 0xFF表示接收所有地址
 */
void SimpleCDNET::setFilter(uint8_t filter) {
    _cdbus.setFilter(filter);
}

/**
 * @brief 设置通信波特率
 * @param baud 波特率值
 * @details 设置底层CDBUS的通信波特率
 */
void SimpleCDNET::setBaudRate(uint32_t baud) {
    _cdbus.setBaudRate(baud);
}

/**
 * @brief 启用/禁用多播功能
 * @param enable true启用，false禁用
 * @details 控制多播数据包的接收和处理
 */
void SimpleCDNET::enableMulticast(bool enable) {
    _multicast_enabled = enable;
}

/**
 * @brief 启用/禁用多网络功能
 * @param enable true启用，false禁用
 * @details 控制多网络环境的支持
 */
void SimpleCDNET::enableMultiNet(bool enable) {
    _multi_net_enabled = enable;
}

/**
 * @brief 设置网络ID
 * @param net_id 网络ID
 * @details 配置当前网络标识符
 * 
 * @note 用于多网络环境区分
 */
void SimpleCDNET::setNetworkId(uint8_t net_id) {
    _net_id = net_id;
}

/**
 * @brief 设置MAC地址
 * @param mac MAC地址
 * @details 配置设备MAC地址
 * 
 * @note 用于网络中的设备识别
 */
void SimpleCDNET::setMacAddress(uint8_t mac) {
    _mac_address = mac;
}

/**
 * @brief 初始化CDNET协议栈
 * @details CDNET协议栈初始化由CDBUS处理
 *          可在此添加CDNET特定的初始化逻辑
 * 
 * @note 当前实现委托给CDBUS
 */
void SimpleCDNET::initializeCDNET() {
    /* CDNET初始化由CDBUS处理 */
    /* 可在此添加CDNET特定的初始化逻辑 */
}

/**
 * @brief 初始化CDNET核心
 * @details 初始化CDNET核心命名空间和接口
 *          配置网络路由和缓冲区管理
 */
void SimpleCDNET::initializeCore() {
    /* 初始化CDNET核心命名空间 */
    cdn_init_ns(&_cdnet_ns, &_free_pkt, &_free_frm);
    
    /* 添加网络接口配置 */
    cdn_add_intf(&_cdnet_ns, (void*)&_cdbus, _net_id, _mac_address);
}

/**
 * @brief 发送数据包（高级接口）
 * @param sock 套接字指针
 * @param pkt 数据包指针
 * @details 使用CDNET核心发送数据包
 * 
 * @note 需要预先绑定套接字
 * @note 支持高级路由功能
 */
void SimpleCDNET::sendPacket(cdn_sock_t *sock, cdn_pkt_t *pkt) {
    /* 使用CDNET核心发送数据包 */
    cdn_sock_sendto(sock, pkt);
}

/**
 * @brief 接收数据包（高级接口）
 * @param sock 套接字指针
 * @return 数据包指针，无数据返回NULL
 * @details 使用CDNET核心接收数据包
 * 
 * @note 需要预先绑定套接字
 * @note 支持高级路由功能
 */
cdn_pkt_t* SimpleCDNET::receivePacket(cdn_sock_t *sock) {
    /* 使用CDNET核心接收数据包 */
    return cdn_sock_recvfrom(sock);
}

/**
 * @brief 绑定套接字到端口
 * @param sock 套接字指针
 * @param port 端口号
 * @return 绑定结果（0成功，负值失败）
 * @details 将套接字绑定到指定端口
 * 
 * @note 需要在使用套接字前绑定
 * @note 支持Layer 0和Layer 1端口
 */
int SimpleCDNET::bindSocket(cdn_sock_t *sock, uint16_t port) {
    /* 配置套接字参数 */
    sock->port = port;
    sock->ns = &_cdnet_ns;
    
    /* 使用CDNET核心绑定套接字 */
    return cdn_sock_bind(sock);
}